package domain;

import java.util.Date ;
import java.util.HashSet ;
import java.util.Set ;

import junit.framework.Assert ;
import persistence.CorruptDataException ;
import persistence.PersistenceController ;
import persistence.PersistenceFactory ;
import util.Bug ;
import util.NotFoundException ;
import domain.user.Login ;

/**
 * @author idan
 */
public class StatisticsServerTest extends AbstractServerTest
{
	private static final int AMOUNT_OF_ELEMENTS_TO_TEST = 3 ;

	private StatisticsServer server ;
	private StatisticsServer emptyServer ;

	public StatisticsServerTest() throws CorruptDataException
	{
		super() ;
	}

	/**
	 * Test method for {@link domain.StatisticsServer#StatisticsServer(PersistenceFactory)}.
	 * Test method for {@link domain.StatisticsServer#close()}.
	 */
	public void testConstructorsDestructors()
	{
		Login login = null ;
		login = this.server.createLogin(1, new Date()) ;
		this.server.close() ;

		StatisticsServer serverClone = null ;
		try
		{
			serverClone = new StatisticsServer(this.persistenceGenerator) ;
			Assert.assertEquals(login.getTime(), serverClone.getLogin(login.getId()).getTime()) ;
		}
		catch (final CorruptDataException e)
		{
			Assert.fail("database corruption") ;
		}
		catch (final NotFoundException e)
		{
			Assert.fail("elements were not properly saved") ;
		}
		finally
		{
			if (serverClone != null)
			{
				serverClone.close() ;
			}
		}
	}

	/**
	 * Test method for {@link domain.StatisticsServer#createLogin(long, java.util.Date)}.
	 */
	public void testCreateLogin() throws NotFoundException
	{
		final Date loginTime = new Date(2346234) ;
		Login login = this.server.createLogin(4, loginTime) ;
		Assert.assertEquals(4, login.getUserId()) ;
		Assert.assertEquals(loginTime, login.getTime()) ;
		Assert.assertSame(login, this.server.getLogin(login.getId())) ;
	}

	/**
	 * Test method for {@link domain.StatisticsServer#flush()}.
	 * Test method for {@link domain.StatisticsServer#flush(domain.user.Login)}.
	 */
	public void testFlush()
	{
		StatisticsServer otherServer = null ;
		try
		{
			final Login login = this.server.createLogin(90, new Date(77431)) ;
			this.server.flush(login) ;
			otherServer = new StatisticsServer(this.persistenceGenerator) ;
			Assert.assertEquals(login.getTime(), this.server.getLogin(login.getId()).getTime()) ;
			otherServer.close() ;

			final Login login2 = this.server.createLogin(91, new Date(9999)) ;
			this.server.flush() ;
			otherServer = new StatisticsServer(this.persistenceGenerator) ;
			Assert.assertEquals(login2.getTime(), otherServer.getLogin(login2.getId()).getTime()) ;
			otherServer.close() ;
		}
		catch (final CorruptDataException e)
		{
			if (otherServer != null)
			{
				otherServer.close() ;
			}
			Assert.fail() ;
		}
		catch (final NotFoundException e)
		{
			if (otherServer != null)
			{
				otherServer.close() ;
			}
			Assert.fail() ;
		}
	}

	/**
	 * Test method for {@link domain.StatisticsServer#getAllLogins()}.
	 */
	public void testGetAllLogins()
	{
		Assert.assertTrue(this.emptyServer.getAllLogins().isEmpty()) ;

		final Set<Login> created = new HashSet<Login>() ;
		for (int i = 0 ; i < StatisticsServerTest.AMOUNT_OF_ELEMENTS_TO_TEST ; i++)
		{
			final Login temp = this.server.createLogin(200+i, new Date(200000+i*100000)) ;
			created.add(temp) ;
		}

		final Set<Login> obtained = this.server.getAllLogins() ;
		Assert.assertEquals(created.size(), obtained.size()) ;
		Assert.assertEquals(created, obtained) ;

	}

	/**
	 * Test method for {@link domain.StatisticsServer#getLogin(long)}.
	 */
	public void testGetUser()
	{
		try
		{
			final Login created = this.server.createLogin(50, new Date(50)) ;
			final Login obtained = this.server.getLogin(created.getId()) ;
			Assert.assertSame(created, obtained) ;
		}
		catch (final NotFoundException e)
		{
			Assert.fail() ;
		}

		try
		{
			final Login obtained = this.emptyServer.getLogin(30) ;
			Assert.fail("fabricated user: " + obtained) ;
		}
		catch (final NotFoundException e)
		{
			// success
		}

		Login created ;
		try
		{
			created = this.server.createLogin(51, new Date(51000)) ;
			final Login obtained = this.server.getLogin(created.getId()) ;
			Assert.assertSame(created, obtained) ;
		}
		catch (final NotFoundException e)
		{
			Assert.fail() ;
		}


	}

	@Override
	protected void clearDatabase()
	{
		try
		{
			PersistenceFactory freshPersistenceBuilder = this
			.newPersistenceGenerator(PersistenceController.BUILD_NEW, false) ;
			freshPersistenceBuilder.newLoginPersistence().close() ;
		}
		catch (CorruptDataException e)
		{
			throw new Bug("report corrupt data when no data expected") ;
		}
	}

	@Override
	protected void setUp() throws Exception
	{
		super.setUp() ;
		this.server = new StatisticsServer(this.persistenceGenerator) ;
		this.emptyServer = new StatisticsServer(this.newPersistenceGenerator(PersistenceController.BUILD_NEW, false)) ;
	}
}
